home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH6 / SRC / BSPLINE2.FRM < prev    next >
Text File  |  1996-04-01  |  11KB  |  425 lines

  1. VERSION 4.00
  2. Begin VB.Form BsplineForm 
  3.    Caption         =   "B-spline"
  4.    ClientHeight    =   5430
  5.    ClientLeft      =   2175
  6.    ClientTop       =   930
  7.    ClientWidth     =   4830
  8.    Height          =   6120
  9.    Left            =   2115
  10.    LinkTopic       =   "Form1"
  11.    ScaleHeight     =   362
  12.    ScaleMode       =   3  'Pixel
  13.    ScaleWidth      =   322
  14.    Top             =   300
  15.    Width           =   4950
  16.    Begin VB.CheckBox ShowTCheck 
  17.       Caption         =   "Show t Values"
  18.       Height          =   255
  19.       Left            =   1680
  20.       TabIndex        =   8
  21.       Top             =   300
  22.       Width           =   1755
  23.    End
  24.    Begin VB.TextBox KText 
  25.       Height          =   285
  26.       Left            =   1140
  27.       TabIndex        =   6
  28.       Text            =   "3"
  29.       Top             =   45
  30.       Width           =   375
  31.    End
  32.    Begin VB.CommandButton CmdNew 
  33.       Caption         =   "New"
  34.       Enabled         =   0   'False
  35.       Height          =   375
  36.       Left            =   4320
  37.       TabIndex        =   5
  38.       Top             =   0
  39.       Width           =   495
  40.    End
  41.    Begin VB.CommandButton CmdGo 
  42.       Caption         =   "Go"
  43.       Default         =   -1  'True
  44.       Enabled         =   0   'False
  45.       Height          =   375
  46.       Left            =   3600
  47.       TabIndex        =   4
  48.       Top             =   0
  49.       Width           =   495
  50.    End
  51.    Begin VB.CheckBox ControlCheck 
  52.       Caption         =   "Show Control Points"
  53.       Height          =   255
  54.       Left            =   1680
  55.       TabIndex        =   3
  56.       Top             =   0
  57.       Value           =   1  'Checked
  58.       Width           =   1755
  59.    End
  60.    Begin VB.TextBox DtText 
  61.       Height          =   285
  62.       Left            =   240
  63.       TabIndex        =   2
  64.       Text            =   "0.05"
  65.       Top             =   45
  66.       Width           =   615
  67.    End
  68.    Begin VB.PictureBox Canvas 
  69.       AutoRedraw      =   -1  'True
  70.       Height          =   4815
  71.       Left            =   0
  72.       ScaleHeight     =   317
  73.       ScaleMode       =   3  'Pixel
  74.       ScaleWidth      =   317
  75.       TabIndex        =   0
  76.       Top             =   600
  77.       Width           =   4815
  78.    End
  79.    Begin VB.Label Label1 
  80.       Caption         =   "K"
  81.       Height          =   255
  82.       Index           =   0
  83.       Left            =   960
  84.       TabIndex        =   7
  85.       Top             =   60
  86.       Width           =   255
  87.    End
  88.    Begin VB.Label Label1 
  89.       Caption         =   "dt"
  90.       Height          =   255
  91.       Index           =   1
  92.       Left            =   0
  93.       TabIndex        =   1
  94.       Top             =   60
  95.       Width           =   255
  96.    End
  97.    Begin VB.Menu mnuFile 
  98.       Caption         =   "&File"
  99.       Begin VB.Menu mnuFileExit 
  100.          Caption         =   "E&xit"
  101.       End
  102.    End
  103. End
  104. Attribute VB_Name = "BsplineForm"
  105. Attribute VB_Creatable = False
  106. Attribute VB_Exposed = False
  107. Option Explicit
  108.  
  109. Const PI = 3.14159
  110.  
  111. Const GAP = 3
  112.  
  113. ' The endpoints are points 1 and 4. The control
  114. ' points are points 2 and 3.
  115. Dim MaxPt As Integer
  116. Dim PtX() As Single
  117. Dim PtY() As Single
  118.  
  119. Dim MakingNew As Boolean
  120.  
  121. ' The index of the point being dragged.
  122. Dim Dragging As Integer
  123.  
  124. Dim OldMode As Integer
  125.  
  126. ' Kvalue determines the smoothness of the curve.
  127. Dim Kvalue As Integer
  128.  
  129. ' t runs between 0 and MaxPt - Kvalue + 2.
  130. Dim MaxT As Single
  131.  
  132.  
  133. ' ************************************************
  134. ' Recursively compute the blending function.
  135. ' ************************************************
  136. Function Blend(i As Integer, k As Integer, t As Single) As Single
  137. Dim numer As Single
  138. Dim denom As Single
  139. Dim value1 As Single
  140. Dim value2 As Single
  141. Dim newt As Single
  142.  
  143.     If i > 0 Then
  144.         newt = t - i + MaxPt + 1
  145.         Do While newt >= MaxPt + 1
  146.             newt = newt - (MaxPt + 1)
  147.         Loop
  148.         Do While newt < 0
  149.             newt = newt + (MaxPt + 1)
  150.         Loop
  151.         Blend = Blend(0, k, newt)
  152.         Exit Function
  153.     End If
  154.  
  155.     ' Base case for the recursion.
  156.     If k = 1 Then
  157.         If Knot(i) <= t And t < Knot(i + 1) Then
  158.             Blend = 1
  159.         ElseIf t = MaxT And Knot(i) <= t And t <= Knot(i + 1) Then
  160.             Blend = 1
  161.         Else
  162.             Blend = 0
  163.         End If
  164.         Exit Function
  165.     End If
  166.     
  167.     denom = Knot(i + k - 1) - Knot(i)
  168.     If denom = 0 Then
  169.         value1 = 0
  170.     Else
  171.         numer = (t - Knot(i)) * Blend(i, k - 1, t)
  172.         value1 = numer / denom
  173.     End If
  174.     
  175.     denom = Knot(i + k) - Knot(i + 1)
  176.     If denom = 0 Then
  177.         value2 = 0
  178.     Else
  179.         numer = (Knot(i + k) - t) * Blend(i + 1, k - 1, t)
  180.         value2 = numer / denom
  181.     End If
  182.  
  183.     Blend = value1 + value2
  184. End Function
  185.  
  186.  
  187. ' ************************************************
  188. ' Draw the curve on the indicated picture box.
  189. ' ************************************************
  190. Sub DrawCurve(pic As PictureBox, start_t As Single, stop_t As Single, dt As Single)
  191. Dim x1 As Single
  192. Dim y1 As Single
  193. Dim t As Single
  194.  
  195.     x1 = X(start_t)
  196.     y1 = Y(start_t)
  197.     pic.Cls
  198.     pic.CurrentX = x1
  199.     pic.CurrentY = y1
  200.     
  201.     t = start_t + dt
  202.     Do While t < stop_t
  203.         x1 = X(t)
  204.         y1 = Y(t)
  205.         pic.Line -(x1, y1)
  206.         t = t + dt
  207.     Loop
  208.     
  209.     x1 = X(stop_t)
  210.     y1 = Y(stop_t)
  211.     pic.Line -(x1, y1)
  212. End Sub
  213.  
  214.  
  215. ' ************************************************
  216. ' Return the ith knot value.
  217. ' ************************************************
  218. Function Knot(i As Integer) As Integer
  219.     Knot = i
  220. End Function
  221.  
  222.  
  223. ' ************************************************
  224. ' The parametric function Y(t).
  225. ' ************************************************
  226. Function Y(t As Single) As Single
  227. Dim i As Integer
  228. Dim value As Single
  229.  
  230.     For i = 0 To MaxPt
  231.         value = value + PtY(i) * Blend(i, Kvalue, t)
  232.     Next i
  233.     Y = value
  234. End Function
  235.  
  236. ' ************************************************
  237. ' The parametric function X(t).
  238. ' ************************************************
  239. Function X(t As Single) As Single
  240. Dim i As Integer
  241. Dim value As Single
  242.  
  243.     For i = 0 To MaxPt
  244.         value = value + PtX(i) * Blend(i, Kvalue, t)
  245.     Next i
  246.     X = value
  247. End Function
  248.  
  249. ' ************************************************
  250. ' Use DrawCurve to draw the Bezier curve.
  251. ' ************************************************
  252. Private Sub DrawBspline()
  253. Const DOTTED = 2
  254.  
  255. Dim dt As Single
  256. Dim i As Integer
  257. Dim oldstyle As Integer
  258.  
  259.     If MaxPt < 0 Then Exit Sub
  260.     
  261.     MousePointer = vbHourglass
  262.     
  263.     Kvalue = CInt(KText.Text)
  264.     dt = CSng(DtText.Text)
  265.     MaxT = MaxPt + 1
  266.     DrawCurve Canvas, 0, MaxT, dt
  267.  
  268.     If ControlCheck.value = vbChecked Then
  269.         ' Draw the control points.
  270.         For i = 0 To MaxPt
  271.             Canvas.Line _
  272.                 (PtX(i) - GAP, PtY(i) - GAP)- _
  273.                 Step(2 * GAP, 2 * GAP), , BF
  274.         Next i
  275.         
  276.         ' Connect the control points.
  277.         oldstyle = Canvas.DrawStyle
  278.         Canvas.DrawStyle = DOTTED
  279.         Canvas.CurrentX = PtX(MaxPt)
  280.         Canvas.CurrentY = PtY(MaxPt)
  281.         For i = 0 To MaxPt
  282.             Canvas.Line -(PtX(i), PtY(i))
  283.         Next i
  284.         Canvas.DrawStyle = oldstyle
  285.     End If
  286.  
  287.     ' Mark the t values if desired.
  288.     If ShowTCheck.value = vbChecked Then
  289.         For dt = 0 To MaxT Step 1#
  290.             Canvas.Line (X(dt), Y(dt) - 5)-Step(0, 10)
  291.             Canvas.Line (X(dt) - 5, Y(dt))-Step(10, 0)
  292.         Next dt
  293.     End If
  294.  
  295.     MousePointer = vbDefault
  296. End Sub
  297.  
  298. ' ************************************************
  299. ' Either collect a new point or select a point and
  300. ' start dragging it.
  301. ' ************************************************
  302. Private Sub Canvas_MouseDown(button As Integer, Shift As Integer, X As Single, Y As Single)
  303. Dim i As Integer
  304.  
  305.     ' If we are selecting points, do so now.
  306.     If MakingNew Then
  307.         MaxPt = MaxPt + 1
  308.         ReDim Preserve PtX(0 To MaxPt)
  309.         ReDim Preserve PtY(0 To MaxPt)
  310.         PtX(MaxPt) = X
  311.         PtY(MaxPt) = Y
  312.         Canvas.Line _
  313.             (X - GAP, Y - GAP)- _
  314.             Step(2 * GAP, 2 * GAP), , BF
  315.         
  316.         If MaxPt >= 3 Then CmdGo.Enabled = True
  317.         
  318.         Exit Sub
  319.     End If
  320.  
  321.     ' Otherwise start dragging a point.
  322.     ' Find a close point.
  323.     For i = 0 To MaxPt
  324.         If Abs(PtX(i) - X) <= GAP And _
  325.            Abs(PtY(i) - Y) <= GAP Then Exit For
  326.     Next i
  327.     If i > MaxPt Then Exit Sub
  328.  
  329.     Dragging = i
  330.     OldMode = Canvas.DrawMode
  331.     Canvas.DrawMode = vbInvert
  332.     PtX(Dragging) = X
  333.     PtY(Dragging) = Y
  334.     Canvas.Line _
  335.         (PtX(Dragging) - GAP, PtY(Dragging) - GAP)- _
  336.         Step(2 * GAP, 2 * GAP), , BF
  337. End Sub
  338.  
  339.  
  340. ' ************************************************
  341. ' Continue dragging a point.
  342. ' ************************************************
  343. Private Sub Canvas_MouseMove(button As Integer, Shift As Integer, X As Single, Y As Single)
  344.     If Dragging < 0 Then Exit Sub
  345.     
  346.     Canvas.Line _
  347.         (PtX(Dragging) - GAP, PtY(Dragging) - GAP)- _
  348.         Step(2 * GAP, 2 * GAP), , BF
  349.     
  350.     PtX(Dragging) = X
  351.     PtY(Dragging) = Y
  352.     
  353.     Canvas.Line _
  354.         (PtX(Dragging) - GAP, PtY(Dragging) - GAP)- _
  355.         Step(2 * GAP, 2 * GAP), , BF
  356. End Sub
  357.  
  358.  
  359. ' ************************************************
  360. ' Finish the drag and redraw the curve.
  361. ' ************************************************
  362. Private Sub Canvas_MouseUp(button As Integer, Shift As Integer, X As Single, Y As Single)
  363.     If Dragging < 0 Then Exit Sub
  364.     
  365.     Canvas.DrawMode = OldMode
  366.     
  367.     PtX(Dragging) = X
  368.     PtY(Dragging) = Y
  369.     Dragging = -1
  370.     
  371.     DrawBspline
  372. End Sub
  373.  
  374.  
  375.  
  376.  
  377. Private Sub CmdGo_Click()
  378.     MakingNew = False
  379.     CmdNew.Enabled = True
  380.     DrawBspline
  381. End Sub
  382.  
  383. ' ************************************************
  384. ' Prepare to get new points.
  385. ' ************************************************
  386. Private Sub CmdNew_Click()
  387.     MaxPt = -1
  388.     CmdGo.Enabled = False
  389.     CmdNew.Enabled = False
  390.     MakingNew = True
  391.     Canvas.Cls
  392. End Sub
  393.  
  394. Private Sub ControlCheck_Click()
  395.     DrawBspline
  396. End Sub
  397.  
  398. Private Sub Form_Load()
  399.     MakingNew = True
  400.     MaxPt = -1
  401.     Dragging = -1
  402. End Sub
  403.  
  404. ' ************************************************
  405. ' Make the canvas as big as possible.
  406. ' ************************************************
  407. Private Sub Form_Resize()
  408.     Canvas.Move 0, Canvas.Top, _
  409.         ScaleWidth, ScaleHeight - Canvas.Top
  410.         
  411.     DrawBspline
  412. End Sub
  413.  
  414.  
  415. Private Sub mnuFileExit_Click()
  416.     Unload Me
  417. End Sub
  418.  
  419.  
  420. Private Sub ShowTCheck_Click()
  421.     DrawBspline
  422. End Sub
  423.  
  424.  
  425.